/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package deatax.display;

import deatax.Player;
import deatax.Tile;
import deatax.markers.Marker;
import deatax.unit.UnitStack;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import javax.media.opengl.GL2;

/**
 *
 * @author Caroline
 */
public abstract class TileRenderer {

    
    public static float borderHeight = 1.0f;
    public static float texture_offset = 0;
    
    private static Texture BORDER_TEXTURE = new Texture("tiles/border.png");
    
    public static float TILE_HEIGHT = 0.3f;
    public static float TILE_BEVEL = 0.1f;
    
    public static float[] hex = genHex(5);
    public static float[] hex_inner = genHex(4.5f);
    public static float[] hex_texture = genHexP(0.5f);

    public static float[][] markerPositions;
    
    private List<String> tile_types = new ArrayList<String>();

    public TileRenderer() {
        if(markerPositions == null){
            markerPositions = new float[10][];
            markerPositions[0] = new float[]{0,0};
            markerPositions[1] = new float[]{0,0};
            for (int i = 2; i < markerPositions.length; i++) {
                markerPositions[i] = genPolygon(i, 0.5f);
            }
        }
    }
    
    
    public static float[] genHex(float radius) {
        float[] hex = new float[12];
        for (int i = 0; i < 4; i += 2) {
            hex[i + 1] = Math.abs((float) Math.sin(Math.toRadians(60 * i)) * radius);
            hex[i] = Math.abs((float) Math.cos(Math.toRadians(60 * i)) * radius);
        }
        hex[4] = -hex[2];
        hex[5] = hex[3];
        hex[6] = -hex[0];
        hex[7] = hex[1];
        hex[8] = -hex[2];
        hex[9] = -hex[3];
        hex[10] = hex[2];
        hex[11] = -hex[3];
        return hex;
    }

    public static float[] genHexP(float radius) {
        float[] hex = genHex(radius);

        System.out.println(hex[0] + "," + hex[3]);

        float x = hex[0];
        float y = hex[3];
        for (int i = 0; i < 12; i += 2) {
            hex[i] += x;
            hex[i + 1] += y;
//            System.out.println(hex[i] + "," + hex[i + 1]);
        }

        return hex;
    }
    
    public static float[] genPolygon(int count, float radius) {

        float[] poly = new float[count*2];
        float angle = 360f/count;

        for (int i = 0, a = 0; i < count*2; i += 2) {
            poly[i] = (float) Math.sin(Math.toRadians(a)) * radius;
            poly[i+1] = (float) Math.cos(Math.toRadians(a)) * radius;
            a += angle;
        }

        return poly;
    }
   
    public static float getHexHeight() {
        return hex[3];
    }

    public static float getHexWidth() {
        return hex[0];
    }
    
    public void addType(String type){
        tile_types.add(type);
    }
    
    public void removeType(String type){
        tile_types.remove(type);
    }
    
    public boolean renders(String type){
        for (String t : tile_types) {
            if(t.equals(type)) return true;
        }
        return false;
    }

    
    
    public void drawMarkers(GL2 gl, Tile t, float px, float py, float rotation, int pass){

        gl.glPushMatrix();

        int count = 0;
        if(t.getImprovement() != null){
            count++;
        }
        for (Entry<Player, ArrayList<UnitStack>> entry : t.getUnits().entrySet()) {
            count += entry.getValue().size();
        }
        
//        gl.glDisable(GL2.GL_DEPTH_TEST);
        gl.glTranslatef(px, py, TILE_BEVEL + 0.1f);
        gl.glRotatef(rotation, 0, 0, 1);
        float[] pos = markerPositions[count];
        int i = 0;
        float scale = getHexHeight();
        
        gl.glScalef(scale,scale,scale);

        if(t.getImprovement() != null){
            gl.glTranslatef(pos[i], pos[i+1], 0);
            t.getImprovement().getMarkerRenderer(t.getOwner()).draw(gl, pass);
            gl.glTranslatef(-pos[i], -pos[i+1], 0);
            i+=2;
        }

        for (Entry<Player, ArrayList<UnitStack>> entry : t.getUnits().entrySet()) {
            count += entry.getValue().size();
            for (UnitStack unitStack : entry.getValue()) {
                gl.glTranslatef(pos[i], pos[i+1], 0);
                unitStack.getMarker().draw(gl,pass);
                gl.glTranslatef(-pos[i], -pos[i+1], 0);
                i+=2;
            }
        }
        gl.glPopMatrix();
//        scale = 1/scale;
//        gl.glScalef(scale, scale, scale);
//        gl.glRotatef(-rotation, 0, 0, 1);
//        gl.glTranslatef(-px, -py, -TILE_BEVEL-0.1f);
//        gl.glEnable(GL2.GL_DEPTH_TEST);
    }

    public void update(long tick){
        texture_offset = (texture_offset + 0.001f) % 1f;
    }

    

    public void draw(GL2 gl, Tile t, float px, float py, float rotation, int pass){
        switch(pass){
            case 0:
                draw(gl, t, px, py, rotation);
                break;
            case 1:
                drawMarkers(gl, t, px, py, rotation, 0);
                break;
            case 2:
                drawBorder(gl, t, px, py, rotation);
                break;
            case 3:
                drawMarkers(gl, t, px, py, rotation, 1);
                break;
        }

        
    }
    
    public void draw(GL2 gl, Tile t, float px, float py, float rotation){
        gl.glColor3f(0.8f, 0.8f, 0.8f);
        gl.glBegin(GL2.GL_LINE_LOOP);
        for (int i = 0; i < 12; i += 2) {
            gl.glVertex3f(hex[i] + px, hex[i + 1] + py, -TILE_HEIGHT);
        }
        gl.glEnd();
        

        if(t.getOwner() != null){
            BoardRenderer.glColorB(gl, t.getOwner().getColor());
        } else if(t.getRegion() != null){
            BoardRenderer.glColorB(gl, t.getRegion().getColour());
        } else {
            gl.glColor3f(0.95f, 0.95f, 0.95f);
        }

        gl.glBegin(GL2.GL_TRIANGLE_STRIP);
        for (int i = 0; i < 13; i += 2) {
            gl.glVertex3f(hex_inner[i % 12] + px, hex_inner[i % 12 + 1] + py, TILE_BEVEL);
            gl.glVertex2f(hex[i % 12] + px, hex[i % 12 + 1] + py);
        }
        gl.glEnd();
        gl.glBegin(GL2.GL_TRIANGLE_STRIP);
        for (int i = 0; i < 13; i += 2) {
            gl.glVertex3f(hex_inner[i % 12] + px, hex_inner[i % 12 + 1] + py, TILE_BEVEL);
            gl.glVertex2f(hex_inner[i % 12] + px, hex_inner[i % 12 + 1] + py);
        }
        gl.glEnd();
        if(t.getRegion() != null){
            BoardRenderer.glColorC(gl, t.getRegion().getColour());
        } else {
            gl.glColor3f(0.7f, 0.7f, 0.7f);
        }
        gl.glBegin(GL2.GL_TRIANGLE_STRIP);
        for (int i = 12; i > -1; i -= 2) {
            gl.glVertex3f(hex[i % 12] + px, hex[i % 12 + 1] + py, -TILE_HEIGHT);
            gl.glVertex2f(hex[i % 12] + px, hex[i % 12 + 1] + py);
        }
        gl.glEnd();
        if(t.getRegion() != null){
            BoardRenderer.glColor(gl, t.getRegion().getColour());
        } else {
            gl.glColor3f(0.9f, 0.9f, 0.9f);
        }

        gl.glLineWidth(2);

//        gl.glBegin(GL2.GL_LINE_LOOP);
//        for (int i = 0; i < 12; i += 2) {
//            gl.glVertex3f(hex_inner[i] + px, hex_inner[i + 1] + py, TILE_BEVEL+0.005f);
//        }
//        gl.glEnd();

        gl.glColor3f(0.8f, 0.8f, 0.8f);
        gl.glBegin(GL2.GL_LINE_STRIP);
        for (int i = 0; i < 8; i += 2) {
            gl.glVertex3f(hex[i] + px, hex[i + 1] + py, 0.02f);
        }
        gl.glEnd();

        gl.glLineWidth(1);
        
        if (t.isHover()) {
            gl.glColor3f(1, 1, 1);
        } else {
            gl.glColor3f(0.90f, 0.90f, 0.90f);
        }
    }


    public void drawHighlight(GL2 gl, Color colour, float px, float py){
            gl.glDisable(GL2.GL_DEPTH_BUFFER);
            gl.glDisable(GL2.GL_CULL_FACE);
            gl.glEnable(GL2.GL_TEXTURE_2D);
            gl.glEnable(GL2.GL_BLEND);
            gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
            BORDER_TEXTURE.bind(gl);
            gl.glTexParameterf( GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_REPEAT );
            BoardRenderer.glColor(gl, colour);
            for (int i = 0; i < 6; i++) {
                drawBorder(gl, px, py, i);
            }
            gl.glDisable(GL2.GL_TEXTURE_2D);
            gl.glEnable(GL2.GL_DEPTH_BUFFER);
            gl.glEnable(GL2.GL_CULL_FACE);
    }

    public  void drawBorder(GL2 gl, Tile t, float px, float py, float rotation){
        
        if(t.getOwner() != null){
//            gl.glDisable(GL2.GL_DEPTH_BUFFER);
            gl.glDisable(GL2.GL_CULL_FACE);
            gl.glEnable(GL2.GL_TEXTURE_2D);
            gl.glEnable(GL2.GL_BLEND);
            gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
            BORDER_TEXTURE.bind(gl);
            gl.glTexParameterf( GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_REPEAT );
            BoardRenderer.glColor(gl, t.getOwner().getColor());
            for (int i = 0, dir = 0; i < 6; i++) {
                dir = (i+3)%6;
                if(t.getNeighbourMap()[5-dir] == null || t.getNeighbourMap()[5-dir].getOwner() != t.getOwner()){
                    drawBorder(gl, px, py, dir);
                }
            }
            gl.glDisable(GL2.GL_TEXTURE_2D);
//            gl.glEnable(GL2.GL_DEPTH_BUFFER);
            gl.glEnable(GL2.GL_CULL_FACE);
        }
    }


    protected void drawBorder(GL2 gl, float px, float py, int direction){
            gl.glBegin(GL2.GL_TRIANGLE_STRIP);
            gl.glTexCoord2f(texture_offset, 0.1f);
            gl.glVertex3f(hex[direction*2] + px, hex[direction*2 + 1] + py, borderHeight);
            gl.glTexCoord2f(texture_offset, 0.9f);
            gl.glVertex3f(hex[direction*2] + px, hex[direction*2 + 1] + py, 0);

            gl.glTexCoord2f(texture_offset+1f, 0.1f);
            gl.glVertex3f(hex[(direction*2+2)%12] + px, hex[(direction*2+3)%12] + py, borderHeight);
            gl.glTexCoord2f(texture_offset+1f, 0.9f);
            gl.glVertex3f(hex[(direction*2+2)%12] + px, hex[(direction*2+3)%12] + py, 0);
            gl.glEnd();
    }
}
